package com.logic.saas.action;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;
import org.apache.struts2.interceptor.SessionAware;
import org.apache.struts2.util.ServletContextAware;
import org.springframework.dao.DataAccessException;
import com.logic.saas.enums.ConstantEnum;
import com.logic.saas.enums.SessionKey;
import com.logic.saas.pojo.User;
import com.logic.saas.util.Pager;
import com.logic.saas.util.SqlErrorCodesUtil;
import com.opensymphony.xwork2.ActionSupport;


@Results({  
	@Result(name="error", location="/WEB-INF/jsp/common/error.jsp"),
	@Result(name="input", location="/WEB-INF/jsp/common/error.jsp")
})
public abstract class BaseAction extends ActionSupport implements SessionAware, ServletResponseAware,ServletRequestAware, ServletContextAware {

	private Logger logger = Logger.getLogger(BaseAction.class.getName());
	
	private static final long serialVersionUID = 1978629054173273146L;
	protected Map<String, Object> session;
	protected HttpServletRequest request;
	protected HttpServletResponse response;
	protected ServletContext context;
	protected Object result;
	protected Map<String, Object> resultMap;
	protected Integer id;
	protected Pager pager;
	public final String JSON = "json";
	public static final String RESULT_NO_PERMISSION = "no_permission";
	public static final String RESULT_SUBSCRIPTION_ERROR = "subscription_error";
	
	public static final String SESSION_TIMEOUT = "session_timeout";
	
	protected String infoMessage;
	protected String errorMesssage;
	
	protected String pageType;
	protected String pageFrom;
	
	
	@Override
	public String execute() throws Exception {
		return SUCCESS;
	}
	
	/**
	 * define the method used to handle with the "input" error. 
	 * Note: just can be applied to the method which will return "JSON".
	 * 
	 * @return
	 * @throws Exception
	 */
	public String handleInputError() throws Exception {
		String errorMessage = this.getText("error.unknown");
		Map<String, Object> resultMap = new HashMap<String, Object>();
		resultMap.put(ConstantEnum.OPERATE_SUCCESS.getValue(), false);

		Map<String, List<String>> fieldsErrorMap = this.getFieldErrors();
		if (fieldsErrorMap != null && fieldsErrorMap.size() > 0) {
			Iterator<Entry<String, List<String>>> it = fieldsErrorMap.entrySet().iterator();
			errorMessage = "";
			while (it.hasNext()) {
				Map.Entry entry = (Map.Entry) it.next();
				String entryValue = entry.getValue().toString();
				if(entryValue.startsWith("[") && entryValue.endsWith("]")){
					entryValue = entryValue.substring(1, entryValue.length()-1);
				}
				errorMessage = errorMessage + entry.getKey().toString() + " : " + entryValue + "<br>";
				//errorMessage = errorMessage + entryValue + "<br>";
			}
		}
		resultMap.put(ConstantEnum.ERROR_MSG.getValue(), errorMessage);
		this.setResult(resultMap);
		return JSON;
	}

	
//	protected SysCache prepareCache(){
//		SysCache instance = null;
//		if(context.getAttribute("SYS_CACHE") == null){
//			instance = SysCache.getInstance();
//			context.setAttribute(ConstantEnum.SYS_CACHE.getValue(), instance);
//		}else{
//			instance = (SysCache)context.getAttribute(ConstantEnum.SYS_CACHE.getValue());
//		}
//		return instance;
//	}
//	
	public String handelDataAccessException(DataAccessException e){
		String errorMsg = this.getText("error.sql.unknow_error");
		if(e != null){
			SQLException sqle = null;
			try {
				sqle = (SQLException) e.getCause();
				if(sqle != null){
					errorMsg = SqlErrorCodesUtil.getErrorMsgByCode(sqle.getErrorCode());
					logger.error("data access error: Error Code-"+sqle.getErrorCode() + "SQL state: " + sqle.getSQLState());
				}
			} catch (Exception e1) {
				e1.printStackTrace();
				errorMsg = e.getMessage();
			}
			
		}
		errorMsg = this.getText("error.label.sql") +" "+ this.getText(errorMsg);
		return errorMsg;
	}
	
	public String getRecordExistsErrorMessage(String tableName,String[] fields){
		String message=tableName+" "+getText("error.record_already_exists");
		for (String field : fields) {
			message+=" "+field;
		}
		message+=".";
		return message;
	}
	
    public User getSessionUser(){
        return (User) session.get(SessionKey.USER);
    }
    
    public void clearSession(){
        
		session.clear();
    }

	public Map<String, Object> getResultMap() {
		return resultMap;
	}

	public void setResultMap(Map<String, Object> resultMap) {
		this.resultMap = resultMap;
	}

	public String getPageType() {
		return pageType;
	}

	public void setPageType(String pageType) {
		this.pageType = pageType;
	}

	public String getPageFrom() {
		return pageFrom;
	}

	public void setPageFrom(String pageFrom) {
		this.pageFrom = pageFrom;
	}
    
	public void setServletContext(ServletContext context) {
		this.context = context;
	}

	public void setServletResponse(HttpServletResponse response) {
		this.response = response;
	}


	public void setServletRequest(HttpServletRequest request) {
		this.request = request;
	}
	public void setSession(Map<String, Object> session) {
		this.session = session;

	}

	public Map<String, Object> getSession() {
		return session;
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public Pager getPager() {
		return pager;
	}

	public void setPager(Pager pager) {
		this.pager = pager;
	}


	public String getInfoMessage() {
		return infoMessage;
	}
	
	public void setInfoMessage(String infoMessage) {
		this.infoMessage = infoMessage;
	}
	
	public String getErrorMesssage() {
		return errorMesssage;
	}
	
	public void setErrorMesssage(String errorMesssage) {
		this.errorMesssage = errorMesssage;
	}

	public Object getResult() {
		return result;
	}

	public void setResult(Object result) {
		this.result = result;
	}
	
}